#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Dougall Johnson, June 7, 2009
# dougallj@gmail.com
# http://code.google.com/color-py/

"""color.py

Crossplatform color font in terminal support. Uses ANSI if not on
Windows, otherwise uses magic Windowsfu.

Methods:
   color.set(color, bright=False, bgcolor=None)
   color.reset()
   color.print_c(color, ... , bright=False, bgcolor=None)

Constants:
   color.colors     A set of all colors.

   color.white
   color.red
   color.green
   color.blue
   color.cyan
   color.magenta
   color.yellow
   color.black

Examples:
   from color import *
   print_c(yellow, " |", end="", bright=True)
   for i in range(19):
           print_c(red, "|||", end="")
           print_c(yellow, "|", end="", bright=True)
   print()

"""

import sys

white   = 0
red     = 1
green   = 2
blue    = 3
cyan    = 4
magenta = 5
yellow  = 6
black   = 7

colors = set([white, red, green, blue, cyan, magenta, yellow, black])


if sys.platform == "win32":
    import ctypes 
    def set(color, bright=False, bgcolor=None):
        """color.set(color, bright=False, bgcolor=None)

        Tells kernel32 to change the color of STDOUT.
        
        Color codes are 4 bits, of the form: bright (8), red (4), green (2),
        blue (1). There are two of these, backround color << 4 | foreground
        color.

        """

        # Clear STDOUT buffer, to cause break in colors
        sys.stdout.flush()

        # Make color code.
        colors = [7, 4, 2, 1, 3, 5, 6, 0]
        foreground = colors[color] | int(bright) << 3
        background = colors[black]
        if bgcolor:
            background = colors[bgcolor]
        col = background << 4 | foreground

        # Tell windows to change the output.
        win = ctypes.windll.kernel32
        win.SetConsoleTextAttribute(win.GetStdHandle(-11), col)
else:
    def set(color, bright=False, bgcolor=None):
        """color.set(color, bright=False, bgcolor=None)

        Prints an ANSI escape escape sequence to change color on all
        non-Windows systems (including Cygwin).

        """

        # Make color code.
        colors = [7, 1, 2, 4, 6, 5, 3, 0]
        colorcode = str(int(bright)) + ";" + str(30 + colors[color])
        if bgcolor:
            colorcode += ";" + str(40 + colors[bgcolor])
        colorcode += "m"

        # Send code to terminal
        escapecode = chr(27) + "["
        sys.stdout.write(escapecode + colorcode)


if sys.platform == "win32":
    def reset():
        """color.reset()

        Sets colors to dull white on black.

        """

        set(white, False, black)
else:
    def reset():
        """color.reset()

        Sets ANSI colors to default.

        """

        escapecode = chr(27) + "["
        colorcode = "0;m"
        sys.stdout.write(escapecode + colorcode)


def print_c(color, *arguments, **keywords):
    """color.print_c(color, ... [, bright=False] [, bgcolor=None] )

    Set color, print, then reset to terminal defaults. Takes all
    arguments that print() takes.

    """

    bright = keywords.pop("bright", False)
    bgcolor = keywords.pop("bgcolor", None)
    set(color, bright, bgcolor)
    print(*arguments, **keywords)
    reset()

